<template>
   
  <!--
     卡片组件:el-card
       shadow:属性值有三个 always | never | hover
  -->
  <el-card class="box-card" shadow="hover">
    <!--按钮组件-->
    <el-button   v-has="'btn.Trademark.add'" type="primary" size="default" :icon="Plus" @click="addTrademark">添加品牌</el-button>
    <!--
      el-table:表格组件
        data:用于设置表格需要展示数据[一定是数组],数组有多少个元素,表格就有多少行
        border:设置表格竖着方向边框
      el-table-column:表格一列
        label:决定这一类顶部标题
        type:这一列显示每一条数据的搜索引数值
        align:这一列文字的对齐方式
        prop:显示表格数据某一个字段-默认用div展示
      温馨提示:表格的每一列展示内容,可以自定义内容,用到作用域插槽
    -->
    <el-table style="margin: 10px 0px" border :data="record">
      <el-table-column
        label="序号"
        type="index"
        width="80"
        align="center"
      ></el-table-column>
      <el-table-column label="品牌名称" prop="tmName"></el-table-column>
      <el-table-column label="品牌LOGO">
        <!--
          每一列内容:可以自定义展示的内容,需要用到作用域插槽,人家列组件，早已经把'坑'留好了
           咱们只是需要'填坑'
           v-slot指令:简写#
         -->
        <template #="{ row, $index }">
          <img :src="row.logoUrl" alt="" style="width: 100px; height: 100px" />
        </template>
      </el-table-column>
      <el-table-column label="品牌操作">
        <template #="{ row, $index }">
          <!--row:即为已有品牌数据,对象-->
          <el-button
            type="warning"
            size="small"
            :icon="Edit"
            @click="updateTradeMark(row)"
          ></el-button>

          <el-popconfirm
            @confirm="removeTradeMark(row.id)"
            :title="`你确定删除${row.tmName}?`"
            :icon="Delete"
            icon-color="red"
            width="200px"
          >
            <template #reference>
              <el-button type="danger" size="small" :icon="Delete"></el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <!--
      分页器组件
       layout:调整分页器子组件布局,通过分页器子组件的名字调整子组件我位置 ->把某一些子组件靠右
       v-model:current-page:分页器当前页码,v-model,达到父子组件数据同步
       v-model:page-size:分页器每一页展示几条数据
       small:决定分页器大的还是小的[需要的是布尔值]
       disabled:是否禁用分页器[需要的也是布尔值]
       background:给分页器按钮添加背景颜色[需要的也是布尔值]
       total:分页器需要展示数据总条数
       prev-text:上一页文字设置
       prev-icon:上一页图标的替换
       current-change:自定义事件,当当前页码发生变化的时候会触发这个回调
       size-change:下拉菜单选择一页3|5|7|9会触发
    -->
    <el-pagination
      layout="prev, pager, next, jumper,->,sizes,total"
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :page-sizes="[3, 5, 7, 9]"
      :small="false"
      :disabled="false"
      :background="true"
      :total="total"
      :prev-icon="Back"
      next-icon="ele-Right"
      @current-change="getTradeMarkList"
      @size-change="sizeHandler"
    />

    <!--新增品牌|修改已有品牌需要的对话框结构--->
    <!--
      el-dialog:对话框组件
        v-model:需要的是一个布尔值,控制对话框显示与隐藏
        title:对话框的标题
        fullscreen:全屏的设置
        modal:遮罩层的设置
        draggable:对话框开启拖拽模式
      el-form:表单组件
    -->
    <el-dialog
      v-model="dialogVisible"
      style="margin-top: 100px"
      :title="tmParams.id ? '修改品牌' : '新增品牌'"
      draggable
    >
      <!--放置表单元素-->
      <el-form
        label-width="100"
        style="width: 80%"
        label-position="right"
        :model="tmParams"
        :rules="rules"
        ref="formEl"
      >
        <el-form-item label="品牌名称" prop="tmName">
          <el-input
            placeholder="请你输入品牌名字"
            v-model="tmParams.tmName"
          ></el-input>
        </el-form-item>
        <el-form-item label="品牌LOGO" prop="logoUrl">
          <!--上传图片组件
              el-uoload:
                action:当前上传图片这个组件,选中图片发请求的post请求,上传图片地址替换,上传图片失败?
                请求路径不携带/app-dev,代理服务器不工作,上传图片业务不会完成
                show-file-list:上传图片是否展示文件名字
                before-upload:上传图片成功之前的钩子---图片上传成功之前会执行一次
                on-success:文件上传成功的钩子


          -->
          <el-upload
            class="avatar-uploader"
            action="/app-dev/admin/product/fileUpload"
            :show-file-list="false"
            :before-upload="beforeAvatarUpload"
            :on-success="handleAvatarSuccess"
          >
            <img
              v-if="tmParams.logoUrl"
              :src="tmParams.logoUrl"
              class="avatar"
            />
            <el-icon v-else class="avatar-uploader-icon"><Upload /></el-icon>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="confirmBtn"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>
  </el-card>
</template>

<script setup lang="ts">
//引入element-plus常用图标组件
import { Plus, Edit, Delete, Back, Upload } from "@element-plus/icons-vue";
import { ref, onMounted, reactive, nextTick } from "vue";
//底下是抄袭官网element-plus:上传图片的代码
import type { UploadProps } from "element-plus";
import { ElMessage } from "element-plus";
//引入品牌管理请求函数
import {
  reqTrademark,
  reqAddOrUpdateTrademark,
  reqRemoveTrademark,
} from "../../../api/product/trademark/index";
//引入ts定义数据类型
import type {
  records,
  responseData,
  trademark,
} from "../../../api/product/trademark/model/index";
//存储分页器当前页码
let currentPage = ref<number>(1);
//存储分页器每一页展示几条数据
let pageSize = ref<number>(3);
//准备两个响应式数据:分别存储品牌数据与总条数
let record = ref<records>([]);
let total = ref<number>(0);
//控制对话框的显示与隐藏响应式数据
let dialogVisible = ref<boolean>(false);
//收集新增品牌的参数
let tmParams = reactive<trademark>({ tmName: "", logoUrl: "" });
//获取el-form组件的VC
let formEl = ref();

//表单验证:自定义校验规则
//自定义校验规则函数:当文本发生变化的时候会出发
const validatorTmName = (rules, value, callBack) => {
  //rules:element-plus注入的规则对象
  //value:表单元素输入的内容
  //callBack:表单验证放行函数
  if (/^[\u4e00-\u9fa5]{2,}$/.test(value)) {
    //放行函数,代表输入内容复合规则
    callBack();
  } else {
    //否则,用户输入的文本内容不符合条件
    //需要传递错误文字提示信息
    callBack(new Error("品牌名字汉字大于等于2位"));
  }
};
//表单验证:规则对象的书写
const rules = {
  //品牌名字的校验规则
  //required:true,代表这个表单收集的品牌数据,务必进行表单验证(表单项前面文字多一个五角星)
  //message:表单元素底部显示的提示文字内容
  //trigger:表单验证触发的时机,change(文本发生变化),blur(失却焦点)
  //min:约束表单元素文本最小数值
  //max:约束表单元素文本最大数值
  tmName: [
    { required: true, message: "品牌名字不能为空", trigger: "blur" },
    { trigger: "change", validator: validatorTmName },
  ],
  //因为logoUrl:利用upload组件,触发表单验证规则:change|blur
  //对于upload组件没有任何意义,根本没有文本发生变化|失去焦点的能力
  logoUrl: [{ required: true, message: "品牌LOGO请你上传" }],
};

//组件挂载完毕:发一次请求,获取第一个的品牌的数据
//由于带有分页器功能:获取品牌接口,将来发多次请求[封装成一个函数]
onMounted(() => {
  getTradeMarkList();
});
//获取品牌的函数
const getTradeMarkList = async () => {
  //currentPage:当前页码,默认参数值1
  //pageSize:每一页需要展示多少条数据3
  let result: responseData = await reqTrademark(
    currentPage.value,
    pageSize.value
  );
  //总条数
  total.value = result.total;
  //品牌数据
  record.value = result.records;
};
//分页器下拉框发生变化的时候会触发次回调
const sizeHandler = () => {
  //整理参数:pageSize->不需要整理3|5|7|9,v-model收集到的
  //只要下拉菜单发生变化,当前页码立马归1
  currentPage.value = 1;
  //再次获取已有品牌的数据
  getTradeMarkList();
};
//添加品牌按钮的回调
const addTrademark = () => {
  //点击添加品牌按钮,显示对话框
  dialogVisible.value = true;
  //清空表单验证校验结果
  //ts语句:代表form组件如果有,才调用resetFields，
  //如果form组件没有,不调用resetFields
  // formEl.value?.resetFields();//移出校验结果
  //nextTick:响应式数据发生变化,获取更新后的DOM|VC
  nextTick(() => {
    //重置该表单项，将其值重置为初始值，并移除校验结果
    formEl.value.resetFields();
    //用户点击添加品牌按钮的时候,清空用户上一次收集的表单数据
    tmParams.id = 0;
    tmParams.tmName = "";
    tmParams.logoUrl = "";
  });
};
//文件上传成功的钩子
const handleAvatarSuccess: UploadProps["onSuccess"] = (
  response,
  uploadFile
) => {
  //次函数:图片上传成功的钩子
  //response:即为上传图片成功此请求，服务器返回的数据(包含:图片远程服务器地址)
  //uploadFile:文件对象
  // imageUrl.value = response.data;
  tmParams.logoUrl = response.data;
};
//图片上传成功之前的钩子:图片上传成功之前次函数会执行一次
const beforeAvatarUpload: UploadProps["beforeUpload"] = (rawFile) => {
  //次钩子:经常在上传图片之前,约束上传文件类型与文件大小(约束)
  //rawFile:即为上传的文件对象[看到文件的名字、文件大小]
  //如果文件格式:png|jpeg|gif,可以上传
  //否则不能上传
  if (
    rawFile.type == "image/png" ||
    rawFile.type == "image/jpeg" ||
    rawFile.type == "image/gif"
  ) {
    //约束上传文件的大小
    //1024b->1KB
    //1024KB->1M
    //1024M-1G
    //1024G-1T
    if (rawFile.size / 1024 / 1024 < 50) {
      return true;
    } else {
      ElMessage({
        message: "上传文件不能大于5M",
        type: "error",
      });
    }
  } else {
    return false;
  }
};

//确定按钮的回调
const confirmBtn = async () => {
  //点击确定按钮,目前而言，新增品牌

  //点击确定按钮的时候,el-form表单组件,开始校验表单
  //由于el-upload并非表单元素,没有触发规则验证的时机(change|blur),
  //只能自己手动的让el-form组件进行表单验证
  //校验某一个字段
  // formEl.value.validateField('logoUrl');
  //对于全部表单相:进行表单验证
  //validate方法返回promise:表单验证通过->成功的Promise
  //表单校验某一个字段失败->失败的Promise对象
  await formEl.value.validate();
  try {
    //添加或者修改品牌成功
    await reqAddOrUpdateTrademark(tmParams);
    //对话框隐藏
    dialogVisible.value = false;
    //再次获取品牌的数据
    //修改
    if (tmParams.id) {
      //修改当前页码不变
      getTradeMarkList();
    } else {
      //新增品牌，分页器归第一页
      currentPage.value = 1;
      getTradeMarkList();
    }
    //文字的提示
    ElMessage({
      message: tmParams.id ? "修改成功" : "添加成功",
      type: "success",
    });
  } catch (error) {
    ElMessage({
      message: tmParams.id ? "修改品牌失败" : "添加品牌失败",
      type: "error",
    });
  }
};

//取消按钮的回调
const cancel = () => {
  //隐藏对话框
  dialogVisible.value = false;
};

//更新品牌按钮的回调
const updateTradeMark = (row: trademark) => {
  //显示对话框
  dialogVisible.value = true;
  //表单元素:展示已有品牌的数据
  //新增品牌参数,不需要ID
  //修改已有品牌的数据,需要ID
  //工作时候:看服务器服药什么参数，整理参数看文档去整理
  //清空表单的校验结果
  nextTick(() => {
    //重置该表单项，将其值重置为初始值，并移除校验结果
    formEl.value.resetFields();
    //再把已有的品牌数据进行赋值
    tmParams.id = row.id;
    tmParams.tmName = row.tmName;
    tmParams.logoUrl = row.logoUrl;
  });
};

//气泡确认框确定按钮的回调
const removeTradeMark = async (id: number) => {
  //发请求,通知服务器删除某一个已有的品牌的数据
  try {
    //删除某一个品牌成功
    await reqRemoveTrademark(id);
    //顶部文字提示
    ElMessage({
      type: "success",
      message: "删除成功",
    });
    //删除如果成功,再次获取最新的全部的品牌是数据
    getTradeMarkList();
  } catch (error) {
    ElMessage({
      type: "error",
      message: "删除失败",
    });
  }
};
</script>

<style scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>